<?php

namespace Smallsha\Core;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Smallsha\Core\SmallshaException;

class Jwt
{
    //TODO  单点登陆  黑名单
    public $config = [
        'ttl' => 86400 * 7, //有效期
        'secret' => '@2rS46lzx#6blBBIByA9BYW4CvMjUIME7tYf36z1pDo9nEV#asTE7JdU&yTgutMafRRbIcCoo^o43vn!IW&0P*WUsRuWw&lAVSs',
        'publisher' => 'ccccccc', //发布者
        'recipient' => 'bbbbbb',  //接受者
        'ident' => 'apiv1',  //标识
    ];

    static $instance;

    private function __construct(array $config)
    {

        if (!class_exists('Lcobucci\JWT\Builder')) {
            throw new  SmallshaException("请安装  composer require lcobucci/jwt  扩展");
        }
        $config = array_merge($this->config, $config);
        foreach ($config as $key => $item) {
            $this->{$key} = $item;
        }
    }

    private function __clone()
    {
        // TODO: Implement __clone() method.
    }


    public static function getInstance(array $config)
    {
        if (self::$instance == null) {
            self::$instance = new self($config);
        }
        return self::$instance;
    }


    public function setJwtInfo(array $claims)
    {
        $builder = new Builder();
        $signer = new Sha256();
        $time = time();
        $builder->issuedBy($this->publisher)//发布者
        ->permittedFor($this->recipient)//接收者
        ->identifiedBy($this->ident, true)//对当前token设置的标识
        ->issuedAt($time)//token创建时间
        ->expiresAt(time() + $this->ttl)//过期时间
        ->canOnlyBeUsedAfter($time);//当前时间在这个时间前，token不能使用

        foreach ($claims as $k => $v) {
            $builder = $builder->withClaim($k, $v); // 自定义数据
        }
        $builder->sign($signer, $this->secret);
        $token = (string)$builder->getToken();
        return $token;
    }

    public function parseUserinfo($key, $token)
    {
        $signer = new Sha256();
        $secret = $this->secret;
        $parse = (new Parser())->parse($token);
        //验证token合法性
        if (!$parse->verify($signer, $secret)) {
            throw new  SmallshaException("Invalid token", 999);
        }
        //验证是否已经过期
        if ($parse->isExpired()) {
            throw new  SmallshaException("'Already expired", 999);
        }
        return $parse->getClaim($key);
    }

}